//
//  PVDDetailViewController.swift
//  ezyform
//  New UI like Formbay
//  Created by MoennigQ on 13/4/18.
//  Copyright © 2018 Client.Solution Pty Ltd. All rights reserved.
//

import UIKit
import CoreLocation
import MBProgressHUD
import HandyJSON
import RealReachability
import YJLocationConverter
import SnapKit
import Photos
import PhotosUI
protocol HideDetailReuploadViewDelegate {
    func hideDetailReuploadView()
}
@objcMembers
class PVDDetailViewController: BaseViewController {
    var skipToWhere: SkipToWhere?
    @IBOutlet weak var loadJobDetailFaildView: InstallationDetailLoadFaildView!
    
    @IBOutlet weak var topBarView: PVDDetailTopBar!
    //tipViewForDesigner
    let tipViewForDesigner = TipViewOnDetailForDesigner()
    //纯代码tab view
    let tabDetailView = PVDDetailTabDetailView()
    let tabAttachmentView = PVDDetailAttachmentView()
    var gwdID: String = ""
    var model = PVDDetailModel()
    var currentCheckListModel: PVDChecklistModel = PVDChecklistModel()
    
    @IBOutlet weak var reuploadView: InstallationDetailReuploadView!
    @IBOutlet weak var reuploadViewHeightContrains: NSLayoutConstraint!
    let bottomView = UIView()
    let startJobBtn: UIButton = UIButton()
    let finishJobBtn: UIButton = UIButton()
    let bottomViewHeight: CGFloat = 73
    var bottomViewHeightConstrain: Constraint?
    
    //current tab value, Tab Detail by default
    var currentTabBtn: UIButton?
    
    var delegate: RefreshReuploadInfoFromDetailDelegate?
    var currentListModel: InstallationListModel?
    var devationLocation = LocationModel()
    var panelInstalledLcation: LocationModel = LocationModel() //点击panel installed时定位到的当前位置信息
    var panelInstalledLatitudeKey: String = ""
    var panelInstalledLongitudeKey: String = ""
    var panelInstalledDateOfCompletionKey: String = ""
    var panelInstalledDateOfCompletion: String = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.initCode()
        self.refreshJobDetail()
        NotificationCenter.default.addObserver(self, selector: #selector(checkLocalInfoToSetReuploadInfo), name: NSNotification.Name(rawValue: "refreshDetailReuploadView"), object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(hideReuploadView), name: NSNotification.Name(rawValue: "hideReuploadView"), object: nil)
        //checklist image上传完后，刷新checklist
        NotificationCenter.default.addObserver(self, selector: #selector(refreshChecklistImages(_:)), name: NSNotification.Name(rawValue: "refreshChecklistImages"), object: nil)
        
        //监听checklist tableview的高度
        self.tabDetailView.checklistTableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.tabAttachmentView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.tabDetailView.inverterInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.tabDetailView.panelInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.tabDetailView.batteryInfoView.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
        self.tabDetailView.signatureListView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
    }
    @objc func refreshChecklistImages(_ notification: NSNotification){
        self.cacheLoadData()
    }
    func initCode(){
        
        //1.title
        self.topBarView.titleLabel.text = self.gwdID
        //2.change tab event on top bar
        topBarView.detailBtn.addTarget(self, action: #selector(changeTab(_:)), for: UIControl.Event.touchUpInside)
        topBarView.attachmentBtn.addTarget(self, action: #selector(changeTab(_:)), for: UIControl.Event.touchUpInside)
        //reupload view
        reuploadView.reuploadClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if Connectivity.isConnectedToInternet,let pvdId = strongSelf.model.pvd_id {
                    let vc = InstallationDetailReuploadViewController()
                strongSelf.definesPresentationContext = true
                    vc.reuploadDataType = "3"//
                    vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
                    //required when
                    vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
                    vc.installtionIds = [pvdId]
                    vc.refreshClosure = { (uploadAllDataSuccessFlag) in
                        strongSelf.loadData(true)
                        
                    }
                strongSelf.navigationController?.present(vc, animated: true, completion: nil)
            }else{
                strongSelf.showFailureInfo()
            }
        }
        
        //bottom view
        bottomView.backgroundColor = UIColor.white
        self.view.addSubview(bottomView)
        bottomView.snp.makeConstraints { (make) in
            make.left.right.equalToSuperview()
            self.bottomViewHeightConstrain = make.height.equalTo(0).constraint
            make.bottom.equalToSuperview()
        }
        let bottomLineView = UIView()
        bottomLineView.backgroundColor = UIColor(red: 208 / 255, green: 208 / 255, blue: 208 / 255, alpha: 1.0)
        bottomView.addSubview(bottomLineView)
        bottomLineView.snp.makeConstraints { (make) in
            make.top.left.right.equalToSuperview()
            make.height.equalTo(1)
        }
        
        bottomView.addSubview(startJobBtn)
        startJobBtn.snp.makeConstraints { (make) in
            make.width.equalTo(181)
            make.height.equalTo(73)
            make.top.equalToSuperview().offset(1)
            make.centerX.equalToSuperview()
        }
        startJobBtn.addTarget(self, action: #selector(startJob), for: UIControl.Event.touchUpInside)
        
        bottomView.addSubview(finishJobBtn)
        finishJobBtn.snp.makeConstraints { (make) in
            make.width.equalTo(181)
            make.height.equalTo(73)
            make.top.equalToSuperview().offset(1)
            make.centerX.equalToSuperview()
        }
        
        finishJobBtn.addTarget(self, action: #selector(finishJob), for: UIControl.Event.touchUpInside)
        //tip view for designer
        tipViewForDesigner.isHidden = true
        tipViewForDesigner.backgroundColor = APPConfig.PVDDetailBackColor
        self.view.addSubview(tipViewForDesigner)
        tipViewForDesigner.snp.makeConstraints { make in
            make.top.equalTo(reuploadView.snp.bottom)
            make.left.right.equalToSuperview()
            make.height.greaterThanOrEqualTo(0)
        }
        //0.tab detail view
        tabDetailView.isHidden = true
        self.view.addSubview(tabDetailView)
        tabDetailView.snp.makeConstraints { make in
            make.top.equalTo(reuploadView.snp.bottom)
            make.left.right.equalToSuperview()
            make.bottom.equalTo(bottomView.snp.top)
        }
        tabDetailView.phoneBtnClickClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().callOwnerPhone(strongSelf.model)
        }
        tabDetailView.copyAddrBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().copyOwnerAddress(strongSelf.model.install_address?.installation_address ?? "",parentView: strongSelf.view)
        }
        tabDetailView.pickupAddressView.copyAddrBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().copyOwnerAddress(strongSelf.model.delivery_address?.map_full_address ?? "",parentView: strongSelf.view)
        }
        tabDetailView.editOwnerInfoBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editOwnerInfo(strongSelf.model,vc: strongSelf)
        }
        tabDetailView.addressBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let addressModel = DeliveryAddressModel()
            let latitude = strongSelf.model.install_address?.location?.latitude
            let longitude = strongSelf.model.install_address?.location?.longitude
            addressModel.latitude = (latitude == nil ? "" : "\(latitude!)")
            addressModel.longitude = (longitude == nil ? "" : "\(longitude!)")
            addressModel.street_number = strongSelf.model.install_address?.street_number ?? ""
            addressModel.street_name = strongSelf.model.install_address?.street_name ?? ""
            addressModel.street_type = strongSelf.model.install_address?.street_type ?? ""
            addressModel.suburb = strongSelf.model.install_address?.suburb ?? ""
            addressModel.state = strongSelf.model.install_address?.state ?? ""
            addressModel.post_code = strongSelf.model.install_address?.post_code ?? ""
            MapNavigationHelper.shared.showMapsOptions(addressModel,vc: strongSelf)
        }
        tabDetailView.pickupAddressView.addressBtnClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let addressModel = DeliveryAddressModel()
            let latitude = strongSelf.model.delivery_address?.latitude
            let longitude = strongSelf.model.delivery_address?.longitude
            addressModel.latitude = latitude == nil ? "" : "\(latitude!)"
            addressModel.longitude = longitude == nil ? "" : "\(latitude!)"
            addressModel.street_number = strongSelf.model.delivery_address?.street_number ?? ""
            addressModel.street_name = strongSelf.model.delivery_address?.street_name ?? ""
            addressModel.street_type = strongSelf.model.delivery_address?.street_type ?? ""
            addressModel.suburb = strongSelf.model.delivery_address?.suburb ?? ""
            addressModel.state = strongSelf.model.delivery_address?.state ?? ""
            addressModel.post_code = strongSelf.model.delivery_address?.post_code ?? ""
            MapNavigationHelper.shared.showMapsOptions(addressModel,vc: strongSelf)
        }
        tabDetailView.checklistTableView.toPanelListClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toPanelNumersVC()
        }
        tabDetailView.checklistTableView.toInverterListClickClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toInverterNumberVC()
        }
        tabDetailView.systemInfoView.editInstallationTypeBtnClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editInstallationType(strongSelf.model,vc: strongSelf)
            }
        }
        tabDetailView.systemInfoView.editBatteryBtnClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editBatteryInfo(strongSelf.model,vc: strongSelf)
            }
        }
        tabDetailView.systemInfoView.editGridConnectdClosure = {[weak self] in
            guard let strongSelf = self else {return}
            if strongSelf.model.canEditPVDDetailFlag {
                InstallationDetailVCHelper.shared().editGridConnectdInfo(strongSelf.model,vc: strongSelf)
            }
        }
        tabDetailView.systemInfoView.spvTipBtn.addTarget(self, action: #selector(spvTipBtnClick), for: UIControl.Event.touchUpInside)
        //
        tabDetailView.panelInfoView.editPanelBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editPanelInfo(strongSelf.model,vc: strongSelf)
        }
        tabDetailView.inverterInfoView.editInverterBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editInverterInfo(strongSelf.model,vc: strongSelf)
        }
        tabDetailView.batteryInfoView.editBatteryBtnClosure = { [weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editBatteryInfo(strongSelf.model,vc: strongSelf)
        }
        //checklist closure
        tabDetailView.checklistTableView.toDERRegisterClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.toDERRegister()
        }
        //checklist
        tabDetailView.checklistTableView.toImageListClosure = { [weak self](currentIndex) in
            guard let strongSelf = self else {return}
            strongSelf.toImageListVC(currentIndex)
        }
        tabDetailView.checklistTableView.toEditTextClosure = { [weak self](checklistModel) in
            guard let strongSelf = self else {return}
            strongSelf.showEditCheckListText(checklistModel)
        }
        tabDetailView.checklistTableView.toPanelInstallClosure = {[weak self] in
            guard let strongSelf = self else {return}
            strongSelf.getDetailBeforePanelInstalled()
        }
        tabDetailView.checklistTableView.toClickChecklitBoolItemClosure = { [weak self](serverModel, index) in
            guard let strongSelf = self else {return}
            strongSelf.toClickBoolItemOfChecklist(serverModel,index: index)
        }
        //signatures
        tabDetailView.signatureListView.toSignatureClosure = {[weak self](type) in
            guard let strongSelf = self else {return}
            InstallationSignatureService().setDataInfo(strongSelf, model: strongSelf.model).toSignature(type)
        }
        tabDetailView.signatureListView.toEditOwnerInfoClosure = {[weak self] in
            guard let strongSelf = self else {return}
            InstallationDetailVCHelper.shared().editOwnerInfo(strongSelf.model,vc: strongSelf)
        }
        //support view
        tabDetailView.signatureListView.toSendEmailClosure = {
            InstallationDetailVCHelper.shared().sendEmail(APPConfig.SupportEmail)
        }
        tabDetailView.signatureListView.toCallPhoneClosure = {
            InstallationDetailVCHelper.shared().callPhone(APPConfig.SupportPhone)
        }
        //attachment view
        tabAttachmentView.isHidden = true
        tabAttachmentView.backgroundColor = APPConfig.PVDDetailBackColor
        self.view.addSubview(tabAttachmentView)
        tabAttachmentView.snp.makeConstraints { make in
            make.top.equalTo(reuploadView.snp.bottom)
            make.left.right.equalToSuperview()
            make.bottom.equalTo(bottomView.snp.top)
        }
        tabAttachmentView.openAttachmentClosure = { [weak self](attachmentType,attachmentModel) in
            guard let strongSelf = self else {return}
            guard let url = attachmentModel.url else {
                return
            }
            let vc = AttachmentViewController()
            vc.attchmentType = .PVDDetailAttachment
            vc.attachmentURL = url
            vc.attachmentTitle = attachmentType
            strongSelf.navigationController?.pushViewController(vc, animated: false)

        }
        tabAttachmentView.nocUploadFooterView.uploadPhotoClosure = {[weak self] in
            guard let strongSelf = self else {return}
            let alertController = UIAlertController(title: NSLocalizedString("ChooseOption", comment: ""), message: nil, preferredStyle: .actionSheet)
            let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel, handler: nil)
            
            let library = UIAlertAction(title: NSLocalizedString("Photolibrary", comment: ""), style: .default, handler: {  action in
                strongSelf.selectFromPhotosLibrary()
            })
            let takePhoto = UIAlertAction(title: NSLocalizedString("TakePhoto", comment: ""), style: .default, handler: { action in
                AVCaptureDevice.requestAccess(for: AVMediaType.video) { (status) in
                    DispatchQueue.main.async {
                        if status {
                            let vc = NOCTakePhotoViewController()
                            vc.confirmClosure = {[weak self] (originalImage) in
                                guard let strongSelf = self else {return}
                                strongSelf.uploadAttachment(originalImage)
                            }
                            vc.modalPresentationStyle = .fullScreen
                            strongSelf.present(vc, animated: true, completion: nil)
                        }else{
                            strongSelf.alertViewWithMsg(message: NSLocalizedString("camera.permission", comment: ""))
                        }
                    }
                    
                }
            })
            alertController.addAction(cancel)
            alertController.addAction(takePhoto)
            alertController.addAction(library)
            
            if Tool.getCurrentDeviceType() == APPConfig.iPadType {
                alertController.modalPresentationStyle = UIModalPresentationStyle.popover
                
                if let popPresenter:UIPopoverPresentationController = alertController.popoverPresentationController {
                    popPresenter.sourceView = strongSelf.tabAttachmentView.nocUploadFooterView.uploadPhotoBtn
                    popPresenter.sourceRect = strongSelf.tabAttachmentView.nocUploadFooterView.uploadPhotoBtn.bounds
                    strongSelf.present(alertController, animated: true, completion: nil)
                }
                
            }else{
                strongSelf.present(alertController, animated: true, completion: {})
            }
            
        }
        //由于网络原因加载失败显示loadJobDetailFaildView，job detail全部不显示
        self.loadJobDetailFaildView.retryBtn.addTarget(self, action: #selector(refreshJobDetail), for: UIControl.Event.touchUpInside)
        //
        self.currentTabBtn = self.topBarView.detailBtn
    }
    @objc func selectFromPhotosLibrary(){
        if #available(iOS 14, *) {//iOS 14之后的相册选择（包括14）
            let level = PHAccessLevel.readWrite
            PHPhotoLibrary.requestAuthorization(for: level){ [weak self](status) in
                guard let strongSelf = self else {return}
                DispatchQueue.main.async {
                    if status == .authorized {//全部相片
                        var configuration = PHPickerConfiguration()
                        configuration.filter = .images
                        configuration.selectionLimit = 1//最多选择1个
                        let picker = PHPickerViewController(configuration: configuration)
                        picker.delegate = strongSelf
                        picker.modalPresentationStyle = .overFullScreen
                        strongSelf.present(picker, animated: true)
                    }else if status == .limited{//部分相片
                        strongSelf.selectFromPhotosLibraryBefore()
                    }else {//无权限
                        strongSelf.alertViewWithMsg(message: NSLocalizedString("photos.permission", comment: ""))
                        return
                    }
                }
            }
        }else{//14以前的
            PHPhotoLibrary.requestAuthorization({ [weak self](status) in
                guard let strongSelf = self else {return}
                DispatchQueue.main.async {
                    if status == .authorized {//有权限
                        strongSelf.selectFromPhotosLibraryBefore()
                    }else{//无权限
                        strongSelf.alertViewWithMsg(message: NSLocalizedString("photos.permission", comment: ""))
                        return
                    }
                }
            })
        }
    }
    //iOS 14之前的相册选择（不包括14）
    fileprivate func selectFromPhotosLibraryBefore(){
        _ = self.presentHGImagePicker(maxSelected: 1) { [weak self](assets) in
            guard let strongSelf = self else {return}
            if assets.count > 0 {
                for i in 0  ..< assets.count {
                    if let originImage = Tool.shared.getUIImage(asset: assets[i]) {
                        strongSelf.uploadAttachment(originImage)
                    }
                }
            }
        }
    }
    func uploadAttachment(_ resultImage: UIImage){
        let attachmentData = Tool.shared.resetSizeOfImageData(source_image: resultImage)
        Tool.shared.showLoadingView()
        let vm = PVDDetailViewModel()
        vm.setBlockAfterNetwork({ (result) -> Void in
            Tool.shared.hideLoadingView()
            if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
                self.tabAttachmentView.tableView.reloadData()
            }
            self.alertViewWithMsg(message: "Upload success")
        }) { (code,msg) -> Void in
            Tool.shared.hideLoadingView()
            self.alertViewWithMsg(message: msg)
        }
        vm.uploadAttachment(attachmentData)
    }
    func toImageListVC(_ index: Int){
        guard index < self.model.pvd_checklists.count else {
            return
        }
        //如果当前checklist是mid-installation check-up或者testing and commissioning checklist而且上一步没有完成
        let serverModel = self.model.pvd_checklists[index]
        let checklistID = serverModel.id ?? 0
        if (checklistID == ChecklistFixedId.midInstall.rawValue || checklistID == ChecklistFixedId.testAndCommission.rawValue) && serverModel.preChecklistDone == false{
            let alertMsg = "Please take '\(serverModel.preChecklistTitle)'"
            self.alertViewWithMsg("Temporary Locked",message: alertMsg,cancelBtnStr: "Dismiss")
        }else{
            self.forwardToImageListVC(index)
        }
    }
    private func forwardToImageListVC(_ index: Int){
        let vc =  InstallationImageListViewController()
        vc.model = self.model
        vc.delegate = self
        vc.currentCheckListModel = self.model.pvd_checklists[index]
        vc.hideDetailReuploadViewDelegate = self
        self.navigationController?.pushViewController(vc,animated: false)
    }
    func toClickBoolItemOfChecklist(_ serverModel: PVDChecklistModel, index: IndexPath){
        guard let id = serverModel.id, let pvdID = APPConfig.loginInfo.currentPVDId else {
            return
        }
        let localChecklist = DBManager.shared.loadChecklistDataByChecklistId(pvdId: pvdID, checklistId: id)
        self.currentCheckListModel.pvdId = APPConfig.loginInfo.currentPVDId
        self.currentCheckListModel.id = serverModel.id
        self.currentCheckListModel.is_required = serverModel.is_required
        self.currentCheckListModel.type = serverModel.type
        self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
        self.currentCheckListModel.title = serverModel.title
        //1.local data exist
        if localChecklist.dbId != nil {
            if localChecklist.answer == "true" {
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.answer = ""
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.full_name = ""
            }else{
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.answer = "true"
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
            }
        }else{
            if serverModel.answer == "true" {
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.answer = ""
                self.currentCheckListModel.answered_at = ""
                self.currentCheckListModel.full_name = ""
                
            }else{
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.answer = "true"
                self.currentCheckListModel.answered_at = Tool.shared.getCurrentDatetime()
                self.currentCheckListModel.full_name = APPConfig.loginInfo.fullName
                
            }
        }
        DBManager.shared.insertChecklistData(model: self.currentCheckListModel)
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
        self.tabDetailView.checklistTableView.refreshData(self.model)
        self.uploadCheckListWithoutImage(index)
    }
    @objc func refreshJobDetail(){//此方法用在refresh和retry,这两个地方需要检查是否有重新签名的提示，不做它用
        //每次都重新拿下Accreditation Number，用于判断当前用户是否是Installer
        Tool.shared.showLoadingView()
        SystemInfoService.shared().loadMyInformation {[weak self] in
            guard let strongSelf = self else {return}
            Tool.shared.hideLoadingView()
            strongSelf.loadData(false, showFaildFlag: true,checkIfNeedResignFlag: true)
        } faildClosure: {[weak self](code,err) in
            guard let strongSelf = self else {return}
            Tool.shared.hideLoadingView()
            strongSelf.resetUIAfterLoad(false,showLoadFaildViewFlag: true)
            strongSelf.setRefreshBtn()
            strongSelf.showErrorInfo(code,err)
        }
    }
    //loadSuccessFlag: true加载成功, showLoadFaildViewFlag:true显示
    func resetUIAfterLoad(_ loadSuccessFlag: Bool,showLoadFaildViewFlag: Bool = false){
        if loadSuccessFlag {
            self.topBarView.isHidden = false
            self.loadJobDetailFaildView.isHidden = true
            if let tabBtn = self.currentTabBtn{
                self.changeTab(tabBtn)
            }
        }else{
            self.topBarView.isHidden = true
            self.tabDetailView.isHidden = true
            self.tabAttachmentView.isHidden = true
            //
            self.bottomView.isHidden = true
            self.bottomViewHeightConstrain?.update(offset: 0)
            startJobBtn.setImage(nil, for: UIControl.State.normal)
            finishJobBtn.setImage(nil, for: UIControl.State.normal)
            self.hideReuploadView()
            self.loadJobDetailFaildView.isHidden = !showLoadFaildViewFlag
        }
    }
    //notloadingFlag is false by default for first loading and refresh data
    func loadData(_ notLoadingFlag: Bool,showFaildFlag: Bool = false,checkIfNeedResignFlag: Bool = false)
    {
        //set block
        let viewModel = PVDDetailViewModel()
        viewModel.setBlockAfterNetwork({ (result) -> Void in
            if !notLoadingFlag {
                Tool.shared.hideLoadingView()
            }
            if let responseData = result as? [String : Any], let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
                if self.gwdID.count == 0 {
                    self.topBarView.titleLabel.text = self.model.gwt_id
                }
            }
            self.dealDataAfterLoadData()
            if let msg = self.model.re_sign_statement_message, checkIfNeedResignFlag && msg != "" && Connectivity.isConnectedToInternet {//true表示需要检查是否有重新签名的提示信息
                self.alertViewWithMsg(message: msg) {
                    self.readResignStatementMsg()
                }
            }
            
        }) { (code, error) -> Void in
            if !notLoadingFlag {
                Tool.shared.hideLoadingView()
            }
            self.setRefreshBtn()
            if error == RequestErrorType.NetworkError.rawValue{//网络不可用错误
                self.resetUIAfterLoad(false,showLoadFaildViewFlag: true)
                if showFaildFlag {
                    self.showFailureInfo()
                }
            }else{
                self.resetUIAfterLoad(false,showLoadFaildViewFlag: false)
                self.showErrorInfo(code, error)
            }
        }
        if !notLoadingFlag {
            //add Loading view
            Tool.shared.showLoadingView()
        }
        viewModel.getInstallationsDetail()
    }
    
    fileprivate func dealDataAfterLoadData(){
        
        InstallationDetailVCHelper.shared().getAllLocalData(self.model)
        //
        self.tabDetailView.signatureListView.setData(self.model)
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        self.checkIfDisplayTipViewForDesigner()
        self.tabDetailView.checklistTableView.refreshData(self.model)
        self.tabAttachmentView.model = self.model
        self.tabAttachmentView.tableView.reloadData()
        self.setDataAfterLoad()
        //先把有的按钮显示出来,等有网络请求完再刷新
        self.getLocalErrorHistory()
        //是否显示小铃铛消息
        self.checkJobMsg()
        
        self.panelInstalledLatitudeKey = "\(String(describing: self.model.pvd_id))" + "Latitude"
        self.panelInstalledLongitudeKey = "\(String(describing: self.model.pvd_id))" + "Longitude"
        self.panelInstalledDateOfCompletionKey = "\(String(describing: self.model.pvd_id))" + "DateOfCompletion"
        //如果panel installed了，将缓存到本地的date of completion 清除掉
        if let spvCheck = self.model.spv_check, let spvInstalled = self.model.spv_installed, spvCheck && spvInstalled {
            UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
        }
        self.resetUIAfterLoad(true,showLoadFaildViewFlag: false)
        //是否跳转到的panel tab 页面，跳转完成后置空
        if let toWhere = self.skipToWhere {
            self.tabDetailView.scrollView.layoutIfNeeded()
            switch toWhere {
            case .Panel,.Inverter,.Checklist:
                self.tabDetailView.scrollView.scrollToView(view: self.tabDetailView.checklistTableView, animated: false)
                if toWhere == .Panel {
                    self.toPanelNumersVC(false)
                }else if toWhere == .Inverter{
                    self.toInverterNumberVC(false)
                }
            case .Signature:
                if Tool.getCurrentDeviceType() == APPConfig.iPadType {
                    self.tabDetailView.scrollView.scrollToBottom()
                }else{
                    self.tabDetailView.scrollView.scrollToView(view: self.tabDetailView.signatureListView, animated: false)
                }
            }
            self.skipToWhere = nil
        }
    }
    func readResignStatementMsg(){
        let vm = PVDDetailViewModel()
        vm.setBlockAfterNetwork { result in
            if let data = result as? PVDDetailModel{
                self.model.re_sign_statement_message = data.re_sign_statement_message
            }
        } errorBlock: { _,_ in
            
        }

        vm.readResignStatementMsg()
    }
    func checkIfDisplayTipViewForDesigner(){
        if self.model.isInstallerFlag{//installer
            self.tipViewForDesigner.isHidden = true
            self.tabDetailView.snp.remakeConstraints { make in
                make.top.equalTo(reuploadView.snp.bottom)
                make.left.right.equalToSuperview()
                make.bottom.equalTo(bottomView.snp.top)
            }
        }else{//designer
            self.tipViewForDesigner.isHidden = false
            self.tabDetailView.snp.remakeConstraints { make in
                make.top.equalTo(tipViewForDesigner.snp.bottom)
                make.left.right.equalToSuperview()
                make.bottom.equalTo(bottomView.snp.top)
            }
        }
    }
    @objc func checkLocalInfoToSetReuploadInfo(){
        if Connectivity.isConnectedToInternet && GlobalOperationQueue.operations.count > 0{
            self.hideReuploadView()
        }else if self.model.checkListModifyFlag || self.model.panelNumbersModifyFlag || self.model.inverterNumbersModifyFlag || self.model.signaturesModifyFlag{//有任何本地数据，要显示Reupload
            self.reuploadView.setReuploadInfo(true)
            self.reuploadViewHeightContrains.constant = 50
        }
    }
    @objc func hideReuploadView(){
        self.reuploadView.setReuploadInfo(false)
        self.reuploadViewHeightContrains.constant = 0
    }
    func setDataAfterLoad(){
        //0.set start job btn or finish job btn
        self.updateBottomViewByJobStatus()
        //1.set detail info
        self.tabDetailView.setData(self.model)
        
        if let spvCheck = self.model.spv_check, spvCheck {
            //            let spvInstalled = (self.model.spv_installed == nil ? false : self.model.spv_installed!)
            //            //已经panel installed时，不能编辑地址和时间
            //            if let spvCheck = self.model.spv_check, spv_check && spvInstalled  {
            //                self.editInstallationAddressBtn.isHidden = true
            //            }else{//没有panel installed时，可编辑地址和时间
            //                self.editInstallationAddressBtn.isHidden = false
            //            }
            
        }else{
            //            let jobStatus = self.model.job_status.lowercased()
            //            //非SPV Job，finish后不能编辑地址和时间
            //            if jobStatus.contains("2") {
            //                self.editInstallationAddressBtn.isHidden = true
            //            }else{//非SPV Job，finish前不能编辑地址和时间
            //                self.editInstallationAddressBtn.isHidden = false
            //            }
            
        }
        //4.signatures
        self.refreshSignatureListForLocalData()
        //6.select tab detail by default
        if let tabBtn = self.currentTabBtn{
            self.changeTab(tabBtn)
        }
    }
    func checkJobMsg(){
        //installer才检查
        if self.model.isInstallerFlag{
            let vm = SystemViewModel()
            vm.setBlockAfterNetwork { (result) in
                if let dic = result as? NSArray{
                    if let data = try? JSONSerialization.data(withJSONObject: dic, options: []){
                        do{
                            let list = try JSONDecoder().decode([JobNotReadModel].self, from: data)
                            if list.count > 0{
                                let notReadModel = list[0]
                                if let newMsgCnt = notReadModel.new_message_count,newMsgCnt > 0{//服务器上有未读数据，则拉取
                                    self.getNewJobMsg()
                                }else{//服务器上没有新数据，则使用本地数据
                                    self.getLocalErrorHistory()
                                }
                            }
                            
                        }catch {//原因是Json中的数据类型和Model中的数据类型不一致导致的
                            print("convert JSON data to model failed")
                        }
                    }
                }
            } errorBlock: { (_,_) in
                self.getLocalErrorHistory()
            }
            vm.getErrorNotRead()
        }else{
            self.setNavigationBarItem()
        }
    }
    func getNewJobMsg(){
        let vm = SystemViewModel()
        vm.setBlockAfterNetwork { (result) in
            if let dic = result as? NSArray{
                if let data = try? JSONSerialization.data(withJSONObject: dic, options: []){
                    do{
                        let list = try JSONDecoder().decode([JobErrorModel].self, from: data)
                        if list.count > 0{
                            for model in list{
                                DBManager.shared.insertJobErrorHistory(model)
                            }
                        }
                        //
                        self.getLocalErrorHistory()
                    }catch {//原因是Json中的数据类型和Model中的数据类型不一致导致的
                        print("convert JSON data to model failed")
                    }
                }
            }
        } errorBlock: { (_,_) in
            self.getLocalErrorHistory()
        }
        vm.getErrorHistories()
    }
    func getLocalErrorHistory(){
        let notReadFlag = DBManager.shared.checkJobErrorHistoryNotRead()
        self.setNavigationBarItem(notReadFlag)
    }
    func setNavigationBarItem(_ haveNewFlag: Bool = false){
        //2.job button: schedules, installing, unqualified
        let jobStatus: String = self.model.job_status ?? ""
        if model.isInstallerFlag {//installer
            
            var items: [UIBarButtonItem] = [UIBarButtonItem]()
            //refresh
            let btn1 = UIButton(type: .custom)
            btn1.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
            btn1.setImage(UIImage(named: "installation_detail_refresh_icon"), for: .normal)
            btn1.addTarget(self, action: #selector(refreshJobDetail), for: .touchUpInside)
            let item1 = UIBarButtonItem(customView: btn1)
            items.append(item1)
            //reopen
            if jobStatus == "2" {
                let btn = UIButton(type: .custom)
                btn.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
                btn.setImage(UIImage(named: "installation_detail_reopen_icon"), for: .normal)
                btn.addTarget(self, action: #selector(reopenJob), for: .touchUpInside)
                let item = UIBarButtonItem(customView: btn)
                items.append(item)
            }
            //Job msg
            let btn = UIButton(type: .custom)
            btn.frame = CGRect(x: 0, y: 0, width: 30, height: 24)
            var iconName = "installation_detail_jobmsg_icon"
            if haveNewFlag {
                iconName = "installation_detail_jobmsg_newmsg_icon"
            }
            btn.setImage(UIImage(named: iconName), for: .normal)
            btn.addTarget(self, action: #selector(toJobMessage), for: .touchUpInside)
            let item = UIBarButtonItem(customView: btn)
            items.append(item)
            
            self.navigationItem.setRightBarButtonItems(items, animated: true)
        }else{//非installer
            self.setRefreshBtn()
        }
    }
    func setRefreshBtn(){
        let item = UIBarButtonItem(image: UIImage(named: "installation_detail_refresh_icon"), style: UIBarButtonItem.Style.plain, target: self, action: #selector(refreshJobDetail))
        self.navigationItem.setRightBarButtonItems([item], animated: true)
    }
    @objc func toJobMessage(){
        let vc = JobErrorHistoriesViewController()
        vc.delegate = self
        vc.gwtId = self.model.gwt_id ?? ""
        self.navigationController?.pushViewController(vc, animated: false)
    }
    func updateBottomViewByJobStatus(){
        if let jobStatus = model.job_status {
            if jobStatus == "0" && model.isInstallerFlag {//scheduled且当前用户是installer
                self.bottomView.isHidden = false
                self.bottomViewHeightConstrain?.update(offset: bottomViewHeight + 1)
                finishJobBtn.isHidden = true
                startJobBtn.isHidden = false
                startJobBtn.setImage(UIImage(named: "installation_detail_startjob_icon"), for: UIControl.State.normal)
                finishJobBtn.setImage(nil, for: UIControl.State.normal)
            }else if (jobStatus == "1" || jobStatus == "3")  && model.isInstallerFlag {//installing or unqualified且当前用户是installer
                self.bottomView.isHidden = false
                self.bottomViewHeightConstrain?.update(offset: bottomViewHeight + 1)
                finishJobBtn.isHidden = false
                startJobBtn.isHidden = true
                finishJobBtn.setImage(UIImage(named: "installation_detail_finishjob_icon"), for: UIControl.State.normal)
                
                startJobBtn.setImage(nil, for: UIControl.State.normal)
            }else {//installed,非installer
                self.bottomView.isHidden = true
                self.bottomViewHeightConstrain?.update(offset: 0)
                startJobBtn.setImage(nil, for: UIControl.State.normal)
                finishJobBtn.setImage(nil, for: UIControl.State.normal)
            }
        }
    }
    func loadDataAndToContinue( _ toContinueType: String)
    {
        //compatible with old panel numbers in local to new data structures（panel numbers in child table）
        //                print(APPConfig.loginInfo.currentPVDId)
        
        //set block
        let viewModel = PVDDetailViewModel()
        viewModel.setBlockAfterNetwork({ (result) -> Void in
            Tool.shared.hideLoadingView()
            if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                self.model.copyAllValuesOfModel(data)
            }
            InstallationDetailVCHelper.shared().getAllLocalData(self.model)
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            
            self.tabDetailView.checklistTableView.refreshData(self.model)
            self.tabAttachmentView.tableView.reloadData()
            self.setDataAfterLoad()
            self.checkJobMsg()
            self.panelInstalledLatitudeKey = "\(String(describing: self.model.pvd_id))" + "Latitude"
            self.panelInstalledLongitudeKey = "\(String(describing: self.model.pvd_id))" + "Longitude"
            self.panelInstalledDateOfCompletionKey = "\(String(describing: self.model.pvd_id))" + "DateOfCompletion"
            //如果panel installed了，将缓存到本地的date of completion 清除掉
            if let spvCheck = self.model.spv_check, let spvInstalled = self.model.spv_installed, spvCheck && spvInstalled {
                UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
            }
            
            self.resetUIAfterLoad(true)
            //本地数据全部上传完毕后
            if  toContinueType == "1" {//continue finish job
                self.finishJob()
            }else if toContinueType == "2"{//continue panel installed
                self.checkSPVPanelInstalledAfterUploadLocalData()
            }
        }) { (code, error) -> Void in
            if error == RequestErrorType.NetworkError.rawValue{
                self.resetUIAfterLoad(false,showLoadFaildViewFlag: true)
            }else{
                self.resetUIAfterLoad(false)
            }
            self.setRefreshBtn()
            Tool.shared.hideLoadingView()
            self.showErrorInfo(code, error)
        }
        //add Loading view
        //本地数据全部上传完毕后)
        if toContinueType == "1" {//finish job
            Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.finishJob", comment: ""))
        }else if toContinueType == "2" {//panel installed
            Tool.shared.showLoadingView("Checking...")
        }
        viewModel.getInstallationsDetail()
    }
    //缓存数据
    func cacheLoadData(_ loadingText: String = "" , closure:(()->Void)? = nil)
    {
        if Connectivity.isConnectedToInternet {
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                if loadingText != ""{
                    Tool.shared.hideLoadingView()
                }
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                    self.dealDataAfterLoadData()
                    closure?()
                }
                
            }) { (code, error) -> Void in
                if loadingText != ""{
                    Tool.shared.hideLoadingView()
                }
                self.alertViewWithMsg(message: error)
            }
            if loadingText != ""{
                Tool.shared.showLoadingView(loadingText)
            }
            vm.getInstallationsDetail()
        }else{
            if loadingText != ""{
                self.showFailureInfo()
            }
        }
    }
    
    @IBAction func editInstallationAddressBtnClick(_ sender: Any) {
        let vc =  EditJobDetailViewController()
        vc.model = self.model
        vc.delegate = self
        self.navigationController?.pushViewController(vc,animated: false)
    }
    @objc func spvTipBtnClick() {
        let vc = SPVTipViewController()
        self.definesPresentationContext = true
        vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
        vc.parentVC = self
        
        //required when
        vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
        self.navigationController?.present(vc, animated: true, completion: nil)
    }
    
    
    @objc func changeTab(_ sender: UIButton){
        
        if sender.tag == 0 {//detail
            self.tabDetailView.isHidden = false
            self.tabAttachmentView.isHidden = true
            self.currentTabBtn = self.topBarView.detailBtn
        }else if sender.tag == 1{//attachment
            self.tabDetailView.isHidden = true
            self.tabAttachmentView.isHidden = false
            self.currentTabBtn = self.topBarView.attachmentBtn
        }
        self.topBarView.changeImage(sender.tag)
    }
    
    @objc func startJob(){
        if !Connectivity.isConnectedToInternet {
            self.showFailureInfo()
            return
        }
        self.requestStartJob(APPConfig.currentLocation.combineStr)
    }
    func requestStartJob(_ locationStr: String = ""){
        if Connectivity.isConnectedToInternet {
            let viewModel = PVDDetailViewModel()
            viewModel.setBlockAfterNetwork({(result) -> Void in
                Tool.shared.hideLoadingView()
                //缓存Job Status状态数据
                DispatchQueue.main.async {
                    self.cacheLoadData()
                }
                if let data = result as? PVDDetailModel {
                    self.model.copyAllValuesOfModel(data)
                    self.dealDataAfterLoadData()
                    if let _ = self.currentListModel{
                        self.currentListModel!.status = "Installing"
                    }
                }
                self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.startedJob", comment: ""))
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showErrorInfo(code, error)
            }
            //add Loading view
            Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.startJob", comment: ""))
            viewModel.startJob(locationStr)
        }else{
            self.showFailureInfo()
        }
    }
    @objc func finishJob() {
        if !Connectivity.isConnectedToInternet {
            self.showFailureInfo()
            return
        }

        //local data need to upload before finishi
        if self.model.checkListModifyFlag ||  self.model.signaturesModifyFlag || self.model.panelNumbersModifyFlag || self.model.inverterNumbersModifyFlag{
            self.alertViewWithUpload(message: NSLocalizedString("pvd.detail.localdata.check.uploaded", comment: ""),toContinueType: "1")
        }else{
            self.cacheLoadData(NSLocalizedString("pvd.detail.finishJob", comment: "")) {
                self.requestFinishJobAPI(APPConfig.currentLocation.combineStr)
            }
        }
        
        
    }
    func requestFinishJobAPI(_ loactionStr: String = ""){
        if Connectivity.isConnectedToInternet {
            //校验checklit，signatures，panel numbers所有的必填项
            if InstallationDetailVCHelper.shared().checkRequiredWhenFinishJob(self.model, vc: self) {
                let viewModel = PVDDetailViewModel()
                viewModel.setBlockAfterNetwork({ (result) -> Void in
                    Tool.shared.hideLoadingView()
                    //缓存Job Status状态数据
                    DispatchQueue.main.async {
                        self.cacheLoadData()
                    }
                    if let data = result as? PVDDetailModel{
                        self.model.copyAllValuesOfModel(data)
                        self.dealDataAfterLoadData()
                        if let _ = self.currentListModel{
                            self.currentListModel!.status = "Installed"
                        }
                    }
                    
                    if self.model.der_register {
                        self.alertViewWithDER()
                    }else{
                        self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.finishedJob", comment: "")){
                            if let data = self.model.installer_rating_id{
                                self.toAPPCommnt(data)
                            }
                        }
                    }
                }) {(code, error) -> Void in
                    Tool.shared.hideLoadingView()
                    self.showErrorInfoFormat(code,error)
                    
                }
                //add Loading view
                Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.finishJob", comment: ""))
                viewModel.finishJob(loactionStr)
            }
            
            
        }else{
            self.showFailureInfo()
        }
        
    }
    //APP评分
    func toAPPCommnt(_ rateId: Int){
        guard let navigationVC = self.navigationController else{
            return
        }
        let view = AppCommentView()
        view.submitClosure = { [weak self] (model) in
            guard let strongSelf = self else {return}
            model.id = rateId
            let vm = PVDDetailViewModel()
            vm.setBlockAfterNetwork { result in
                if model.ignoreFlag == false{//submit时才显示submitting
                    Tool.shared.hideLoadingView()
                }
                view.removeFromSuperview()
            } errorBlock: { (code,errMsg) in
                if model.ignoreFlag == false{//submit时才显示submitting
                    Tool.shared.hideLoadingView()
                    strongSelf.alertViewWithMsg(message: errMsg)
                }
            }
            //add Loading view
            if model.ignoreFlag == false{//submit时才显示submitting
                Tool.shared.showLoadingView(NSLocalizedString("Submitting...", comment: ""))
            }
            vm.submitAPPComment(model)
        }
        navigationVC.view.addSubview(view)
        view.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }
    //finish job的时候如果有本地数据，弹出框中增加upload的button
    func alertViewWithUpload(_ title : String = "", message : String,cancelBtnStr: String = "Cancel", textAlignment: NSTextAlignment = .center, toContinueType: String){
        let alertViewController = UIAlertController(title: title, message: "", preferredStyle: UIAlertController.Style.alert)
        
        let cancelAction = UIAlertAction(title: cancelBtnStr, style: .cancel,handler: nil)
        
        let uploadAction = UIAlertAction(title: "Upload&Continue", style: .default){(action) -> Void in
            self.uploadAllLocalData(toContinueType)
        }
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = textAlignment
        let messageText = NSMutableAttributedString(
            string: message,
            attributes: [
                NSAttributedString.Key.paragraphStyle: paragraphStyle,
                NSAttributedString.Key.font: UIFont(name: "Arial", size: 13) as Any,
                NSAttributedString.Key.foregroundColor: UIColor.black
            ]
        )
        
        alertViewController.setValue(messageText, forKey: "attributedMessage")

        alertViewController.addAction(cancelAction)
        alertViewController.addAction(uploadAction)
        self.present(alertViewController, animated: true, completion: nil)
        
    }
    func uploadAllLocalData(_ toContinueType: String){
        guard let pvdId = self.model.pvd_id else {
            return
        }
        if Connectivity.isConnectedToInternet {
            let vc = InstallationDetailReuploadViewController()
            self.definesPresentationContext = true
            vc.reuploadDataType = toContinueType
            vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
            //required when
            vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
            vc.installtionIds = [pvdId]
            vc.refreshClosure = { [weak self](uploadAllDataSuccessFlag) in
                guard let strongSelf = self else {return}
                if uploadAllDataSuccessFlag {//上传成功继续下边的步骤
                    strongSelf.loadDataAndToContinue(toContinueType)
                }else{//上传不成功刷新数据
                    strongSelf.cacheLoadData()
                }
                
                
            }
            self.navigationController?.present(vc, animated: true, completion: nil)
        }else{
            self.showFailureInfo()
        }
    }
    func alertViewWithDER(){
        let vc = FinishJobAlertViewController()
        vc.toDERRegistClose = {
            self.toDERRegister()
        }
        //需要弹出App评分功能
        if let data = self.model.installer_rating_id{
            vc.okClosure = {[weak self] in
                guard let strongSelf = self else {return}
                strongSelf.toAPPCommnt(data)
            }
        }
        self.definesPresentationContext = true
        vc.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
        //required when
        vc.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
        self.navigationController?.present(vc, animated: true, completion: nil)
    }
    @objc func reopenJob(){
        if Connectivity.isConnectedToInternet {
            let viewModel = PVDDetailViewModel()
            viewModel.setBlockAfterNetwork({ (result) -> Void in//
                Tool.shared.hideLoadingView()
                //缓存Job Status状态数据
                DispatchQueue.main.async {
                    self.cacheLoadData()
                }
                
                if let data = result as? PVDDetailModel{
                    self.model.copyAllValuesOfModel(data)
                    self.dealDataAfterLoadData()
                    if let _ = self.currentListModel{
                        self.currentListModel!.status = "Installing"
                    }
                }
                self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.reopenedJob", comment: ""))
            }) {(code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showErrorInfo(code, error)
                
            }
            //add Loading view
            Tool.shared.showLoadingView(NSLocalizedString("pvd.detail.reopenJob", comment: ""))
            viewModel.reopenJob()
        }else{
            self.showFailureInfo()
        }
    }
    func toPanelNumersVC(_ animate: Bool = true) {
        if let jobStatus = self.model.job_status, jobStatus != "0" {
            let vc = PVDPanelNumberViewController()
            //print(model.pvd_id)
            vc.model = self.model
            vc.delegate = self
            vc.hideDetailReuploadViewDelegate = self
            vc.title = self.model.gwt_id
            vc.hidesBottomBarWhenPushed = true
            self.navigationController?.pushViewController(vc, animated: animate)
        }
        
    }
    func toInverterNumberVC(_ animate: Bool = true) {
        if let jobStatus = self.model.job_status, jobStatus != "0" {
            let vc = PVDInverterNumberViewController()
            //print(model.pvd_id)
            vc.model = self.model
            vc.delegate = self
            vc.hideDetailReuploadViewDelegate = self
            vc.title = self.model.gwt_id
            vc.hidesBottomBarWhenPushed = true
            self.navigationController?.pushViewController(vc, animated: animate)
        }
    }
    func editCheckListText(_ serverModel: PVDChecklistModel){
        
        let vc = PVDEditChecklistViewController()
        vc.model = self.model
        vc.serverModel = serverModel
        vc.cacheDelegate = self
        vc.delegate = self
        self.navigationController?.pushViewController(vc, animated: false)
    }
    
    //upload checklist without uploading view
    func uploadCheckListWithoutImage(_ indexPath: IndexPath){
        if !Connectivity.isConnectedToInternet {
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            return
        }
        
        if self.model.checkListModifyFlag {
            //隐藏Detail的ReuploadView
            self.hideReuploadView()
            let group = DispatchGroup()
            for checklistModel in self.model.localChecklists {
                if checklistModel.type != "image" {//text and boolean
                    
                    group.enter()
                    DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "1")
                    GlobalOperationQueue.addOperation {
                        let checklistVM = PVDDetailViewModel()
                        
                        checklistVM.setBlockAfterNetwork({ (result) -> Void in
                            DBManager.shared.deleteChecklsitData(pvdId: self.model.id,checklistId: checklistModel.id!)
                            
                            self.model.pvd_checklists = (JSONDeserializer<PVDChecklistModel>.deserializeModelArrayFrom(json: result as? String) as? Array<PVDChecklistModel>)!
                            group.leave()
                            
                        }) { (code, error) -> Void in
                            DBManager.shared.setUpoadingFlag(checklist_table_name,keyId: checklistModel.dbId!, flag: "0")
                            group.leave()
                            
                        }
                        
                        checklistVM.uploadChecklistDataWithoutImages(self.model,checklistId: checklistModel.id!)
                    }
                }
            }
            group.notify(queue: DispatchQueue.main) {
                InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                //要刷新整个表格，因为Checklist Group 布局要刷新required和optional的完成数量
                self.tabDetailView.checklistTableView.refreshData(self.model)
                self.checkJobMsg()
            }
        }
        
    }
    func getDetailBeforePanelInstalled(){
        //0.在panel install校验前，如果有网络就先拉下网络数据，否则无网直接panel installed
        if Connectivity.isConnectedToInternet {//有网路的处理步骤
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                let oldSPVCheck: Bool? = self.model.spv_check
                
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                }
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                
                self.setDataAfterLoad()
                //校验spv状态是否从abled变成disabled
                if let oldCheck = oldSPVCheck, let newCheck = self.model.spv_check, oldCheck && !newCheck {
                    let alertViewController = UIAlertController(title: "", message: "The retailer has disabled SPV verification for the current job.", preferredStyle: UIAlertController.Style.alert)
                    
                    let okAction = UIAlertAction(title: "OK", style: .cancel) { [unowned self](action) -> Void in
                        self.tabDetailView.checklistTableView.refreshData(self.model)
                    }
                    alertViewController.addAction(okAction)
                    self.present(alertViewController, animated: true, completion: nil)
                }else{
                    if let spvInstalled = self.model.spv_installed, spvInstalled{//如果已经spv installed了，就刷新checklist数据
                        self.tabDetailView.checklistTableView.refreshData(self.model)
                    }else{
                        self.showPanelInstallAlertVC()
                    }
                }
                
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.showPanelInstallAlertVC()
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            vm.getInstallationsDetail()

        }else{
            self.showPanelInstallAlertVC()
        }
    }
    func showPanelInstallAlertVC(){
        //
        let vc = PanelInstallAlertViewController()
        vc.delegate = self
        vc.model = self.model
        if let date = UserDefaults.standard.object(forKey: self.panelInstalledDateOfCompletionKey) as? String {
            vc.cacheDateOfCompletion = date
        }
        self.navigationController?.pushViewController(vc, animated: false)
    }
    
    func checkSPVPanelInstalled(){
        //缓存date of completion时间
        if self.panelInstalledDateOfCompletion != "" {
            UserDefaults.standard.set(self.panelInstalledDateOfCompletion, forKey: self.panelInstalledDateOfCompletionKey)
        }
        //1.检查是否有invalid 的panel number
        for panelModel in self.model.pvd_serial_numbers {
            if panelModel.spv_status?.lowercased() == "invalid" && panelModel.modifyFlag == false {
                self.alertViewWithMsg(message: "Invalid panel serial number. Please confirm and try again.")
                return
            }
        }
        //2.panel number数量是否匹配
        let scannedPanelNumberCnt: String = "\(self.model.pvd_serial_numbers.count + self.model.localPVDSerialNumbers.count)"
        if let systemDetail = self.model.system_detail, let planPanelNumberCnt = systemDetail.number_panels{
            if planPanelNumberCnt != scannedPanelNumberCnt {
                
                self.alertViewWithMsg(message: "The actual number of panels installed do not match with the original quantity.\n\nPanel quantity : " + planPanelNumberCnt + "\nPanel serial numbers: " + scannedPanelNumberCnt)
                return
            }
        }
        
        //3.1 服务器上的panel number图片是否为空
        for panelModel in self.model.pvd_serial_numbers {
            if panelModel.image == nil || panelModel.image == "" {
                self.alertViewWithMsg(message: "Please upload a valid photo of the panel's serial number.")
                return
            }
        }
        //3.2 本地的panel number图片是否为空
        for panelModel in self.model.localPVDSerialNumbers {
            if panelModel.image == nil || panelModel.image == "" {
                self.alertViewWithMsg(message: "Please upload a valid photo of the panel's serial number.")
                return
            }
        }
        //4.是否有网络
        if Connectivity.isConnectedToInternet {//有网路的处理步骤
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                let oldSPVCheck: Bool? = self.model.spv_check
                
                if let responseData = result as? NSDictionary,let data = PVDDetailModel.deserialize(from: responseData){
                    self.model.copyAllValuesOfModel(data)
                }
                //检查是否有本地数据，有的话显示Reupload btn
                self.checkLocalInfoToSetReuploadInfo()
                
                self.setDataAfterLoad()
                //5 校验spv状态是否从abled变成disabled
                if let oldCheck = oldSPVCheck, let newCheck = self.model.spv_check, oldCheck && !newCheck {
                    let alertViewController = UIAlertController(title: "", message: "The retailer has disabled SPV verification for the current job.", preferredStyle: UIAlertController.Style.alert)
                    
                    let okAction = UIAlertAction(title: "OK", style: .cancel) { [unowned self](action) -> Void in
                        self.tabDetailView.checklistTableView.refreshData(self.model)
                    }
                    alertViewController.addAction(okAction)
                    self.present(alertViewController, animated: true, completion: nil)
                }
                //6. panel numbers，Installation address and date of completion，是否有本地数据或者
//                if self.model.panelNumbersModifyFlag || self.model.detailModifyFlag {
                if self.model.panelNumbersModifyFlag || self.model.checkListModifyFlag{
                    self.alertViewWithUpload(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.localpanelnumbers.check.tip", comment: ""),toContinueType: "2")//"2": continue panel installed
                    return
                }
                //7,8
                self.checkSPVPanelInstalledAfterUploadLocalData()
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                self.checkSPVPanelInstalledCommonOther()
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            
            vm.getInstallationsDetail()

        }else{//有网路的处理步骤
            self.checkSPVPanelInstalledCommonOther()
        }
    }
    func checkSPVPanelInstalledAfterUploadLocalData(){
        //7.是否验证了所有的panel numer
        for panelModel in self.model.pvd_serial_numbers{
            if let spvStatus = panelModel.spv_status {
                if spvStatus.lowercased() == "verifying" || spvStatus.lowercased() == "unverified" {
                    self.alertViewWithMsg(message: "The previous panel is still being verified. Please try again later.")
                    return
                }
            }
        }
        //8.Job是否有地址
        let installationAddress = self.model.install_address?.installation_address
        if installationAddress == nil || installationAddress == "" {
            self.alertViewWithMsg(message: "The current job is missing address information, please contact the retailer to fill out and try again.")
            return
        }
        //
        self.checkSPVPanelInstalledCommonOther()
    }
    func checkSPVPanelInstalledCommonOther(){
        
        //9.Installation address的经纬度是否为空
        let installationLocation = self.model.install_address?.location
        if installationLocation == nil || installationLocation?.longitude == nil || installationLocation?.latitude == nil {
            self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.panalNumbers.spv.gps.notlocated", comment: ""))
            return
        }
        
        //10.是否存储了上次Panel Installed的离线经纬度
        //上次存储了定位位置
        if let latitudeValue = UserDefaults.standard.object(forKey: self.panelInstalledLatitudeKey) as? Double, let longitudeValue = UserDefaults.standard.object(forKey: self.panelInstalledLongitudeKey) as? Double {
            self.devationLocation.latitude = latitudeValue
            self.devationLocation.longitude = longitudeValue
//            Tool.shared.showToast(msg: "From cache address\nlatitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checklistTableView)
            self.panelInstallValidateAPI()
        }else{//上次没有存储定位位置
            //11：location 定位是否开启
            let status  = CLLocationManager.authorizationStatus()
            if let spvCheck = self.model.spv_check, spvCheck {
                if status == .denied || status == .restricted {
                    let alert = UIAlertController(title: NSLocalizedString("pvd.detail.panalNumbers.locationservice.tip.title", comment: ""), message: NSLocalizedString("pvd.detail.panalNumbers.locationservice.tip.content", comment: ""), preferredStyle: .alert)
                    
                    let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
                    let settingAction = UIAlertAction(title: "Settings", style: UIAlertAction.Style.default) { (_) in
                        
                        if  UIApplication.shared.canOpenURL(URL(string: UIApplication.openSettingsURLString)!) {
                            UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!, options: [:], completionHandler: nil)
                        }
                    }
                    
                    alert.addAction(cancelAction)
                    alert.addAction(settingAction)
                    
                    present(alert, animated: true, completion: nil)
                    
                }
            }
            //12.能否定位GPS/网络
            self.devationLocation.latitude = nil
            self.devationLocation.longitude = nil
            self.panelInstalledLcation.latitude = nil
            self.panelInstalledLcation.longitude = nil
            LocationManager.shared.subscription(.single).fetchWithCompletion {[weak self](location, error) in
                guard let strongSelf = self else {
                    return
                }
                if location != nil {
                    var currentLocation: CLLocation = location!
                    if Tool.shared.isLocationOutOfChina(location!.coordinate) == false{
                        let gcj02Coordinate = YJLocationConverter.yj_WGS84Convert(toGCJ02: location!.coordinate)
                        currentLocation = CLLocation(latitude: gcj02Coordinate.latitude, longitude: gcj02Coordinate.longitude)
                    }
                    
                    //获取安装位置的经纬度
                    if let installedLocation = strongSelf.model.install_address?.location {
                        if let latitude = installedLocation.latitude, let longitude = installedLocation.longitude {
                            let installedLocation = CLLocation(latitude: latitude, longitude: longitude)
                            
                            //单位是m
                            let distanceFromCurrentLocation = currentLocation.distance(from: installedLocation)
                            
                            //13.当前位置是否在owner 安装地址范围内：不在范围内
                            if let devationSetting = strongSelf.model.installation_position_deviation, distanceFromCurrentLocation > devationSetting{
                                
                                //14.扫描位置是否在安装范围内
                                for panelModel in strongSelf.model.pvd_serial_numbers {
                                    if let latitide = panelModel.latitude, let longitude = panelModel.longitude {
                                        let panelInstalledLocation = CLLocation(latitude: latitide, longitude: longitude)
                                        
                                        let distance = installedLocation.distance(from: panelInstalledLocation)
                                        //获取系统设置的最小距离的值（单位：米）
                                        if let devationSetting = strongSelf.model.installation_position_deviation, distance <= devationSetting{
                                            
                                            strongSelf.devationLocation.latitude = panelInstalledLocation.coordinate.latitude
                                            strongSelf.devationLocation.longitude = panelInstalledLocation.coordinate.longitude
                                            //测试代码要去掉：begin
//                                            var fromStr: String = ""
//                                            if let autoScan = panelModel.auto_scan {
//                                                fromStr = autoScan == 0 ? "From Add Manually:\n" : "From Scan Barcode\n"
//                                            }
                                            
//                                            Tool.shared.showToast(msg: fromStr + "latitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checklistTableView)
                                            //测试代码要去掉： end
                                            break
                                        }
                                    }
                                }
                                //当前位置和扫描位置都不在安装范围内
                                if strongSelf.devationLocation.latitude == nil && strongSelf.devationLocation.longitude == nil {
                                    strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.installaddress.check.tip", comment: ""))
                                }else{//在panel number中存在范围内的经纬度
                                    
                                    let alertViewController = UIAlertController(title: "", message: NSLocalizedString("pvd.detail.checklist.panelinstalled.usescanningaddress.tip.two", comment: ""), preferredStyle: UIAlertController.Style.alert)
                                    
                                    let okAction = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
                                        strongSelf.panelInstallValidateAPI()
                                    }
                                    let noAction = UIAlertAction(title: "No", style: .cancel,handler: nil)
                                    
                                    alertViewController.addAction(okAction)
                                    alertViewController.addAction(noAction)
                                    strongSelf.present(alertViewController, animated: true, completion: nil)
                                }
                                
                            }else{//当前位置是否在owner 安装地址范围内：在范围内
                                strongSelf.panelInstalledLcation.latitude = currentLocation.coordinate.latitude
                                strongSelf.panelInstalledLcation.latitude = currentLocation.coordinate.longitude
                                
                                strongSelf.devationLocation.latitude = currentLocation.coordinate.latitude
                                strongSelf.devationLocation.longitude = currentLocation.coordinate.longitude
                                //测试代码要去掉： begin
//                                Tool.shared.showToast(msg: "From current location\n latitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checklistTableView)
                                //测试代码要去掉： end
                                strongSelf.panelInstallValidateAPI()
                            }
                            
                            
                        }else{
                            
                            strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.installaddress.required.tip", comment: ""))
                            return
                        }
                    }
                    
                }else{//定位失败
                    if let installAddress = strongSelf.model.install_address,let installedLocation = installAddress.location {
                        if let latitude = installedLocation.latitude, let longitude = installedLocation.longitude {
                            let installedLocation = CLLocation(latitude: latitude, longitude: longitude)
                            //14.扫描位置是否在安装范围内
                            for panelModel in strongSelf.model.pvd_serial_numbers {
                                if let latitide = panelModel.latitude, let longitude = panelModel.longitude {
                                    let panelInstalledLocation = CLLocation(latitude: latitide, longitude: longitude)
                                    
                                    let distance = installedLocation.distance(from: panelInstalledLocation)
                                    //获取系统设置的最小距离的值（单位：米）
                                    if let devationSetting = strongSelf.model.installation_position_deviation, distance <= devationSetting{
                                        
                                        strongSelf.devationLocation.latitude = panelInstalledLocation.coordinate.latitude
                                        strongSelf.devationLocation.longitude = panelInstalledLocation.coordinate.longitude
                                        break
                                    }
                                }
                            }
                            if strongSelf.devationLocation.latitude == nil && strongSelf.devationLocation.longitude == nil {
                                strongSelf.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.availableaddress.check.tip", comment: ""))
                            }else{//在panel number中存在范围内的经纬度，提示用户是否使用panel number中的位置
                                
                                let alertViewController = UIAlertController(title: "", message: NSLocalizedString("pvd.detail.checklist.panelinstalled.usescanningaddress.tip", comment: ""), preferredStyle: UIAlertController.Style.alert)
                                
                                let okAction = UIAlertAction(title: "OK", style: .default) { (action) -> Void in
                                    strongSelf.panelInstallValidateAPI()
                                }
                                let noAction = UIAlertAction(title: "No", style: .cancel,handler: nil)
                                
                                alertViewController.addAction(okAction)
                                alertViewController.addAction(noAction)
                                strongSelf.present(alertViewController, animated: true, completion: nil)
                                
                            }
                        }
                    }
                    
                }
            }
        }
    }
    
    func panelInstallValidateAPI()
    {
        //15.有网络直接调用panel installed的 api
        if Connectivity.isConnectedToInternet {
            let vm = PVDDetailViewModel()
            //set block
            vm.setBlockAfterNetwork({ (result) -> Void in
                Tool.shared.hideLoadingView()
                
                //请求成功后，删除保存的经纬度
                UserDefaults.standard.removeObject(forKey: self.panelInstalledLatitudeKey)
                UserDefaults.standard.removeObject(forKey: self.panelInstalledLongitudeKey)
                UserDefaults.standard.removeObject(forKey: self.panelInstalledDateOfCompletionKey)
                //缓存数据，并设置panel instealled为true
                self.loadData(true,checkIfNeedResignFlag: true)
                
            }) { (code, error) -> Void in
                Tool.shared.hideLoadingView()
                if error == RequestErrorType.NetworkError.rawValue{
                    //缓存了当前panel installed地址
                    if let latitude = self.panelInstalledLcation.latitude, let longitude = self.panelInstalledLcation.longitude {
                        UserDefaults.standard.set(latitude, forKey: self.panelInstalledLatitudeKey)
                        UserDefaults.standard.set(longitude, forKey: self.panelInstalledLongitudeKey)
                        //            Tool.shared.showToast(msg: "Save cache address\nlatitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checkListView)
                        self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.getcurrentlocation.withoutnetwork", comment: ""))
                    }else{//使用的是扫描panel number时地址
                        self.alertViewWithMsg(message: "We can't verify your data due to network failure. Please try again later.")
                        
                    }
                }else{
                    self.showErrorInfo(code, error)
                }
            }
            //add Loading view
            Tool.shared.showLoadingView("Checking...")
            vm.panelInstalledValidate(self.devationLocation,dateOfCompletion: self.panelInstalledDateOfCompletion)
        }else{//没有网络，保存panel installed的经纬度
            
            //缓存了当前panel installed地址
            if let latitude = self.panelInstalledLcation.latitude, let longitude = self.panelInstalledLcation.longitude {
                UserDefaults.standard.set(latitude, forKey: self.panelInstalledLatitudeKey)
                UserDefaults.standard.set(longitude, forKey: self.panelInstalledLongitudeKey)
                //            Tool.shared.showToast(msg: "Save cache address\nlatitude: \(self.devationLocation.latitude)" + "\nlongitude:\(self.devationLocation.longitude)", parentView: self.checkListView)
                self.alertViewWithMsg(message: NSLocalizedString("pvd.detail.checklist.panelinstalled.getcurrentlocation.withoutnetwork", comment: ""))
            }else{//使用的是扫描panel number时地址
                self.alertViewWithMsg(message: "We can't verify your data due to network failure. Please try again later.")
                
            }
            
        }
        
    }
    func toDERRegister(){
        if self.model.isInstallerFlag {//当前用户是installer才能操作DER Register
            let vc = DERRegisterViewController()
            if let gwtID = self.model.gwt_id {
                vc.gwtID = gwtID
            }
            self.navigationController?.pushViewController(vc, animated: false)
        }
        
    }
    //监听Contensize是获取Tableview 高度最准确的方法
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?){
        guard let tableView = object as? UITableView else { return  }
        if keyPath == "contentSize" {
            if let value = change?[.newKey]{
                if let size  = value as? CGSize{
                    if tableView == self.tabDetailView.checklistTableView {
                        self.tabDetailView.checklistTableViewHeightConstrains?.update(offset: size.height)
                    }else if tableView == self.tabAttachmentView.tableView {
                        self.tabAttachmentView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.tabDetailView.panelInfoView.tableView{
                        self.tabDetailView.panelInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.tabDetailView.inverterInfoView.tableView{
                        self.tabDetailView.inverterInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }else if tableView == self.tabDetailView.signatureListView {
                        self.tabDetailView.signatureListViewHeightConstaint?.update(offset: size.height)
                    }else if tableView == self.tabDetailView.batteryInfoView.tableView{
                        self.tabDetailView.batteryInfoView.tableViewHeightConstraint?.update(offset: size.height)
                    }
                    
                }
            }
        }
    }

    override func backToPre() {
        super.backToPre()
        Tool.shared.cancelAllNetworkRequestForPVD()
        self.delegate?.refreshReuploadInfo()
    }
    deinit {
        if self.isViewDidLoad{
            self.tabDetailView.checklistTableView.removeObserver(self, forKeyPath: "contentSize")
            self.tabAttachmentView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.tabDetailView.panelInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.tabDetailView.inverterInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.tabDetailView.batteryInfoView.tableView.removeObserver(self, forKeyPath: "contentSize")
            self.tabDetailView.signatureListView.removeObserver(self, forKeyPath: "contentSize")
            NotificationCenter.default.removeObserver(self)
        }
    }
    override func viewDidLayoutSubviews() {
        super.updateViewConstraints()
        self.tabDetailView.panelInfoView.tableView.separatorStyle = .none
        self.tabDetailView.inverterInfoView.tableView.separatorStyle = .none
        self.tabDetailView.batteryInfoView.tableView.separatorStyle = .none
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        Tool.shared.printDebug("\(self) didReceiveMemoryWarning")
    }
}
extension PVDDetailViewController: SignatureViewDelegate,RefreshChecklistDelegate,ReloadDataDelegate,ReloadDataForDeletePanelNumberDelegate,PanelInstallDelegate,ReloadDataForDeleteInverterNumberDelegate,JobErrorMsgDelegate,RefreshPVDDetailChecklistDelegate,HideDetailReuploadViewDelegate {
    //HideDetailReuploadViewDelegate
    func hideDetailReuploadView() {
        self.hideReuploadView()
    }
    //RefreshPVDDetailChecklistDelegate
    func refreshPVDDetailChecklist() {
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        self.tabDetailView.checklistTableView.refreshData(self.model)
    }
    func checkIfHaveReuploadInfo(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
    }
    //JobErrorMsgDelegate
    func recheckJobMsg() {
        //先用本地数据
        self.getLocalErrorHistory()
        self.checkJobMsg()
    }
    //PanelInstallDelegate
    func toPanelInstall(_ dateOfCompletion: String) {
        self.panelInstalledDateOfCompletion = dateOfCompletion
        self.checkSPVPanelInstalled()
    }
    
    //ReloadDataForDeleteInverterNumberDelegate
    func reloadDataForDeleteInverterNumber(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        self.tabDetailView.checklistTableView.reloadData()
    }
    //ReloadDataForDeletePanelNumberDelegate
    //直接用self.model = PVDDetailModel.deserialize(from: result as? NSDictionary)，不影响删除时的数据源，因为tableview在deleterow之前已经处理过数据源了，否则如果用reloadData方法在弱网的情况下数据源会混乱，deleterows容易报错
    func reloadDataForDeletePanelNumber(){
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
        //3.panel numbers
//        let panelCount = self.model.pvd_serial_numbers.count + self.model.localPVDSerialNumbers.count
//        self.tabDetailView.panelNumberCountLabel.text = (panelCount > 0 ? "#\(panelCount)" : "")
        self.tabDetailView.checklistTableView.reloadData()
        self.checkJobMsg()
    }
    //ReloadDataDelegate for cache the latest data
    func reloadData() {
        let viewModel = PVDDetailViewModel()
        viewModel.setBlockAfterNetwork({ (result) -> Void in
            
            //这里不直接用self.model = PVDDetailModel.deserialize(from: result as? NSDictionary),而是直接给里边中变量赋值，是为了不改变self.model的地址，手动增加中的model和这里的是同一个地址，因为地址以改变数据就同步不了了
            if let data = PVDDetailModel.deserialize(from: result as? NSDictionary){
                self.model.copyAllValuesOfModel(data)
            }
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            
            self.tabDetailView.checklistTableView.refreshData(self.model)
            
            self.tabAttachmentView.model = self.model
            self.tabAttachmentView.tableView.reloadData()
            
            self.setDataAfterLoad()
            self.checkJobMsg()
            self.panelInstalledLatitudeKey = "\(String(describing: self.model.pvd_id))" + "Latitude"
            self.panelInstalledLongitudeKey = "\(String(describing: self.model.pvd_id))" + "Longitude"
            
            self.topBarView.isHidden = false
            self.tabDetailView.isHidden = false
            self.tabAttachmentView.isHidden = true
        }) { (code, error) -> Void in
            if error ==  RequestErrorType.NetworkError.rawValue{
                if self.model.pvd_id != nil {
                    InstallationDetailVCHelper.shared().getAllLocalData(self.model)
                    //检查是否有本地数据，有的话显示Reupload btn
                    self.checkLocalInfoToSetReuploadInfo()
                    self.setDataAfterLoad()
                    self.checkJobMsg()
                }else{
                    self.setRefreshBtn()
                }
            }else{
                self.topBarView.isHidden = true
                self.tabDetailView.isHidden = true
                self.tabAttachmentView.isHidden = true
                self.setRefreshBtn()
            }
        }
        
        viewModel.getInstallationsDetail()
    }
    //RefreshChecklistDelegate
    func refreshChecklist() {
        InstallationDetailVCHelper.shared().getLocalCheckList(self.model)
        self.tabDetailView.checklistTableView.refreshData(self.model)
        //检查是否有本地数据，有的话显示Reupload btn
        self.checkLocalInfoToSetReuploadInfo()
    }
    //SignatureViewDelegate
    func refreshSignatureList() {
        self.refreshSignatureListForLocalData()
        self.uploadSignaturesAsync()
    }
    //获取本地数据，刷新签名列表
    func refreshSignatureListForLocalData() {
        InstallationDetailVCHelper.shared().getLocalSignatures(self.model)
        self.tabDetailView.signatureListView.setData(self.model)
    }
    
    //异步上传Signature
    func uploadSignaturesAsync(){
        if !Connectivity.isConnectedToInternet{
            //检查是否有本地数据，有的话显示Reupload btn
            self.checkLocalInfoToSetReuploadInfo()
            return
        }
        if model.signaturesModifyFlag {
            //隐藏Detail的ReuploadView
            self.hideReuploadView()
            InstallationSignatureService().setDataInfo(self, model: self.model).uploadSignatures { [weak self] in
                guard let strongSelf = self else { return }
                strongSelf.cacheLoadData()
            }
        }
    }
    fileprivate func showEditCheckListText(_ serverModel: PVDChecklistModel){
        
        let vc = InstallationEditChecklistTextViewController()
        vc.model = self.model
        vc.serverModel = serverModel
        vc.cacheDelegate = self
        vc.delegate = self
        vc.modalPresentationStyle = .overFullScreen
        self.present(vc, animated: true, completion: nil)
    }
}
extension PVDDetailViewController: PHPickerViewControllerDelegate{
    @available(iOS 14, *)
    func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
        picker.dismiss(animated: true) {//代码必需加到回调中，防止选图片界面dismiss反应慢，导致Add可以点击多次导致增加n多图片
            let itemProviders = results.map(\.itemProvider)
            guard itemProviders.count > 0 else {
                return
            }
            for (_ , itemProvider) in itemProviders.enumerated() where itemProvider.canLoadObject(ofClass: UIImage.self) {
                itemProvider.loadObject(ofClass: UIImage.self) {[weak self] (image, error) in
                    DispatchQueue.main.async {
                        if let strongSelf = self, let resultImage = image as? UIImage{
                            strongSelf.uploadAttachment(resultImage)
                        }
                    }
                }
            }
        }
        
    }
}
